package com.dylan.历史.多线程.并发编程的艺术;

import com.dylan.历史.util.SleepUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.*;

/**
 * Created by Dylan on 2018/9/5.
 */
public class 多线程_CountDownLatch {

    /**
     * 百米赛跑，多个参加赛跑的运动员在听到发令枪响后，开始跑步，到达终点后结束计时，然后统计平均值
     */
    public static void main(String[] args) throws Exception {
        // 跑步者人数
        int num = 10;
        // 发令枪，跑步者开始跑步的标识
        CountDownLatch begin = new CountDownLatch(1);
        // 跑步者到达终点的标识
        CountDownLatch end = new CountDownLatch(num);

        // 创建跑道（线程池），每个跑步者一个赛道（线程数与参加赛跑人数相同）
        ExecutorService track = Executors.newFixedThreadPool(num);
        // 存储所有跑步成绩
        List<Future<Integer>> results = new ArrayList<>();
        // 提交跑步任务
        for (int i = 0; i < num; i++) {
            results.add(track.submit(new Runner(begin, end)));
        }

        // 发令枪响，跑步者开始跑步
        begin.countDown();
        // 等待所有跑步者到达终点
        end.await();

        // 计算成绩
        int totalScore = 0;
        for (Future<Integer> result : results) {
            totalScore += result.get();
        }
        System.out.println("平均成绩为：" + (1.0 * totalScore / num));
        track.shutdown();
    }

    // 跑步者
    static class Runner implements Callable<Integer> {
        private CountDownLatch begin;
        private CountDownLatch end;

        public Runner(CountDownLatch begin, CountDownLatch end) {
            this.begin = begin;
            this.end = end;
        }

        @Override
        public Integer call() throws Exception {
            // 初始化成绩
            int score = new Random().nextInt(20);

            // 等待发令枪响，然后开始跑步
            begin.await();

            System.out.println("选手 " + Thread.currentThread().getName() + " 开始跑步");
            // 开始跑步
            SleepUtils.seconds(score);
            System.out.println("选手 " + Thread.currentThread().getName() + " 完成跑步:" + score);

            // 跑步者跑完全程
            end.countDown();

            return score;
        }
    }
}
